#include "widget.h"
#include "ui_widget.h"
#include <QIcon>


Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    QIcon icon("d:/desk/qtProject/demo/serial_assistant/labixiaoxin.png");
    this->setWindowIcon(icon);
    init();//串口初始化
    dataBuffer = new QString[128];
    isRunning = false;
    lastXPoint = 0;
    timer1 = new QTimer;
    data = new QByteArray;
    qDebug() << "主线程对象的地址: " << QThread::currentThread();
    subThread = new QThread;

    subData = new thread_AcceptData;

    subData->moveToThread(subThread);//把接受数据的类移动到子线程中工作

   //connect(subData,&thread_AcceptData::updateSerialPort,this,&Widget::updatePort);//获取串口号
    connect(subData,&thread_AcceptData::updateSerialPort,this,[=](QList<QSerialPortInfo> list){
        for(auto&info:list)
        {
            qDebug()<<info.description()<<info.portName();
            ui->comboBox_serialPort->addItem(info.portName()+":"+info.description(),info.portName());
        }
    });
    this->subData->serialInit();
    ui->spinBox_frequency->setValue(5);
    connect(subData,&thread_AcceptData::pulse_SysCfg,this,&Widget::handle_PulseSysCgf);
    connect(subData,&thread_AcceptData::updateStatus,this,&Widget::updateStatusHandler);
    connect(subData,&thread_AcceptData::jerkSlot,this,&Widget::jerkHandler);
    connect(subData,&thread_AcceptData::completePack,this,&Widget::reslvePack);
  //  connect(subData,&thread_AcceptData::transferEmit,this,&Widget::hotPlug);
    connect(timer1,&QTimer::timeout,this,&Widget::hotPlug);
    subThread->start();
}

Widget::~Widget()
{
    delete ui;
}

void Widget::updatePort(QList<QSerialPortInfo> port) //把子线程搜索到的端口号添加到ui文件中
{
    for(auto&info:port)
    {
        qDebug()<<info.description()<<info.portName();
        ui->comboBox_serialPort->addItem(info.portName()+":"+info.description(),info.portName());
    }
}


void Widget::init()
{
   /* auto list = QSerialPortInfo::availablePorts();

    for(auto&info:list)
    {
        qDebug()<<"子线程"<<info.description()<<info.portName();
         ui->comboBox_serialPort->addItem(info.portName()+":"+info.description(),info.portName());
    }*/

    /*脉冲端子初始化*/
    ui->comboBox_pulseChose->addItem("Y0");
    ui->comboBox_pulseChose->addItem("Y1");
    ui->comboBox_pulseChose->addItem("Y2");
    ui->comboBox_pulseChose->addItem("Y3");

    /*硬极限端子初始化*/
    ui->comboBox_STOP->addItem("X1");
    ui->comboBox_STOP->addItem("X2");
    ui->comboBox_STOP->addItem("X4");
    ui->comboBox_STOP->addItem("X5");
    ui->sanpleFrequcency->setValue(50);
  // ui->sanpleFrequcency->setReadOnly(true);
   /*方向端子*/
    ui->comboBox_DirTerminal->addItem("Y4");
    ui->comboBox_DirTerminal->addItem("Y5");
    ui->comboBox_DirTerminal->addItem("Y6");
    ui->comboBox_DirTerminal->addItem("Y7");
    plotInit();
}

void Widget::plotInit()
{

    // 生成游标
  /*  tracer = new QCPItemTracer(ui->plot);                                  // 生成游标
    tracer->setPen(QPen(Qt::red));                                         // 轮廓颜色
    tracer->setBrush(QBrush(Qt::red));                                     // 填充颜色
    tracer->setStyle(QCPItemTracer::tsCircle);                             // 圆圈样式
    tracer->setSize(5);
    // 游标说明

    tracerLabel = new QCPItemText(ui->plot);                             // 游标说明
    tracerLabel->setLayer("overlay");                                      // 设置图层为overlay，因为需要频繁刷新
    tracerLabel->setPen(QPen(Qt::black));                                  // 设置游标说明颜色
    tracerLabel->setPositionAlignment(Qt::AlignLeft | Qt::AlignTop);       // 位置
    tracerLabel->position->setParentAnchor(tracer->position);              // 将游标说明锚固在tracer位置处，实现自动跟随
    connect(ui->plot,&QCustomPlot::mouseMove,this,&Widget::myMove);*/

    QPen pen;
    pen.setColor(Qt::blue);
    pen.setWidth(2);


    ui->plot->addGraph();

    ui->plot->graph(0)->rescaleAxes(true);
    ui->plot->graph(0)->setPen(pen);
    ui->plot->graph(0)->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssCircle,2));
    ui->plot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables);//
    ui->plot->legend->setVisible(false);
    ui->plot->xAxis->setRange(0,100);
    ui->plot->yAxis->setRange(0,100);

    QPen pen2;
    pen.setColor(Qt::darkRed);
    pen.setWidth(2);

   ui->plot->addGraph();
   ui->plot->graph(1)->rescaleAxes(true);
   ui->plot->graph(1)->setPen(pen2);
   ui->plot->graph(1)->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssCircle,2));
   ui->plot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables);//
   ui->plot->legend->setVisible(false);
    ui->plot->replot();

}

void Widget:: updataXAxis(int pulse_Cnt ,int puleFre )//更新数据
{
    //double currentTime = QDateTime::currentDateTime().toMSecsSinceEpoch() / 1000.0;

    // 模拟接收到的脉冲数据，实际应用中从下位机接收数据
    //int pulseCount = qrand() % 100;  // 随机生成一个脉冲计数
    lastXPoint += 10;

    ui->plot->graph(0)->addData(lastXPoint, pulse_Cnt);
    ui->plot->graph(1)->addData(lastXPoint, puleFre);
    // 设置x轴范围为当前时间前后的10秒
    ui->plot->xAxis->setRange(lastXPoint - 500, lastXPoint + 500);
    // 刷新图表
    ui->plot->replot();
}
void Widget::myMove(QMouseEvent *e)
{

    // 获得鼠标位置处对应的横坐标数据x
    double x = ui->plot->xAxis->pixelToCoord(e->pos().x());
    tracer->setGraph(ui->plot->graph(0));         // 将游标和该曲线图层连接
    tracer->setGraphKey(x);                         // 将游标横坐标设置成刚获得的横坐标数据x
    tracer->setInterpolating(true);                 // 游标的纵坐标可以通过曲线数据线性插值自动获得
    tracer->updatePosition();                       // 使得刚设置游标的横纵坐标位置生效
    // 更新游标说明的内容
    double xValue = tracer->position->key();
    double yValue = tracer->position->value();
    tracerLabel->setText(QString("x = %1, y = %2").arg(xValue).arg(yValue));
    ui->plot->replot();                           // 重绘
}
void Widget::on_Button_Link_pressed()//连接串口按钮
{

    if(this->subData->serial.isOpen())
    {
         this->subData->serial.close();
         ui->Button_Link->setText("打开串口");
         QMessageBox::information(this,"InforMation","串口已断开",QMessageBox::Ok);
         return;
    }
    auto portName = ui->comboBox_serialPort->currentData().toString();
    lastPortName = portName;
    qDebug() << "lastPortName" << lastPortName;
    this->subData->serial.setPortName(portName);
    this->subData->serial.setBaudRate(115200);//
    this->subData->serial.setDataBits(QSerialPort::DataBits(8));//
    this->subData->serial.setStopBits( QSerialPort::StopBits(1));//
    this->subData->serial.setParity( QSerialPort::Parity(0));//

    if(!this->subData->serial.open(QIODevice::ReadWrite))
    {
            QMessageBox::warning(this,"warning",portName+"open faild"+this->subData->serial.errorString());
            return;
     }
     else
     {

             QMessageBox::information(this,"InforMation","Link Successed",QMessageBox::Ok);
             timer1->start(1000);  //USB串口号识别
             ui->Button_Link->setText("关闭串口");

     }

    QByteArray * data_Init = new QByteArray;
    data_Init->append("#A00");
    checkCode = checkCode + '0' + '0';//功能码 数据包
    data_Init->append(checkCode);
    data_Init->append("!");
    this->subData->serial.write(*data_Init);
    checkCode = 0;
    //delete data_Init;

}
/*清空接收区*/
void Widget::on_button_acpt_clear_released()
{
   ui->acceptText->clear();
}
/*清空发送区*/
void Widget::on_clear_InputBox_released()
{
   ui->inputText->clear();
}

void Widget::on_button_SendMessage_released()//发送数据
{
       //auto dataString = ui->inputText->toPlainText(); //+ui->sendNewLineChx->isChecked()?"\r\n":"";
       //serial.write(dataString.toLocal8Bit());
     QString inputHex =  ui->inputText->toPlainText();
     QByteArray  byteArray = QByteArray::fromHex(inputHex.toUtf8());
     if(this->subData->serial.isOpen())
     {
         this->subData->serial.write(byteArray);
         qDebug()<<"Data Sent:"<<byteArray.toHex();
     }else
     {
        QMessageBox::warning(this,"警告","串口未打开", QMessageBox:: Ok);
     }
}

void Widget::on_checkBox_Hex_toggled(bool checked)//16进制显示
{
    if(checked)
        displayHex();
    else
        displayText();

}

void Widget::displayHex()//hex显示
{
    //先把数据拿出来 转成16进制 再显示回去
    auto file = ui->acceptText->toPlainText();
   //ui->acceptText->clear();
    auto file_hex = file.toLocal8Bit().toHex(' ').toUpper();

    ui->acceptText->setPlainText(file_hex);

}

void Widget::displayText()//文本显示
{
    //先把数据拿出来 转成文本 再写回去
    auto file = ui->acceptText->toPlainText();
   //ui->acceptText->clear();
    auto fileData = QByteArray::fromHex(file.toLocal8Bit());
    ui->acceptText->setPlainText(fileData);
}

void Widget::on_btn_Save_released()//保存按钮
{
    QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"), "", tr("CSV FILE(*.csv);;ALL files(*.*)"));
    if (!fileName.isEmpty())
    {
        if (!fileName.endsWith(".csv", Qt::CaseInsensitive))
        {
            fileName += ".csv";
        }

        // 打开文件以写入
        QFile file(fileName);
        if (file.open(QIODevice::WriteOnly | QIODevice::Text))
        {
            QTextStream out(&file);

            // 保存当前的轴范围（缩放级别）
            double xRangeLower = ui->plot->xAxis->range().lower;
            double xRangeUpper = ui->plot->xAxis->range().upper;
            double yRangeLower = ui->plot->yAxis->range().lower;
            double yRangeUpper = ui->plot->yAxis->range().upper;

            // 将轴范围写入文件
            out << "X Axis Range:," << xRangeLower << "," << xRangeUpper << "\n";
            out << "Y Axis Range:," << yRangeLower << "," << yRangeUpper << "\n\n";

            // 遍历所有图形并保存数据
            for (int i = 0; i < ui->plot->graphCount(); ++i)
            {
                QCPGraph *graph = ui->plot->graph(i); // 获取第 i 个图形
                int dataCount = graph->data()->size(); // 获取数据点的数量

                // 为每条曲线添加标识符并写入数据
                out << "Graph " << (i + 1) << "\n";  // 标识曲线编号
                out << "X,Y" << "\n";  // 写入列标题

                for (int j = 0; j < dataCount; ++j)  // 遍历数据点
                {
                    auto dataPoint = graph->data()->at(j);
                    out << dataPoint->key << "," << dataPoint->value << "\n"; // 保存数据，逗号分隔
                }

                // 在每条曲线数据后面添加一个空行作为分隔符
                out << "\n";
            }

            out.flush();
            file.close();
        }
        else
        {
            // 处理文件打开失败的情况
            QMessageBox::warning(this, tr("Error"), tr("Cannot save file."));
        }
    }
    else
    {
        // 用户取消了保存操作
        return;
    }

}

void Widget:: on_btn_History_released()//历史回看
{

    QString fileName = QFileDialog::getOpenFileName(this, "选择 CSV 文件", "", "CSV Files (*.csv)");
    if (fileName.isEmpty()) return;

    QFile file(fileName);
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        QMessageBox::warning(this, "错误", "无法打开文件");
        return;
    }

    QTextStream in(&file);
    QString line;
    double xRangeLower = 0, xRangeUpper = 0;
    double yRangeLower = 0, yRangeUpper = 0;
    bool rangesRead = false;
    QVector<QVector<double>> allXData, allYData;  // 用于存储每条曲线的数据
    QVector<double> xData, yData;
    bool readingCurveData = false;  // 用于标识是否正在读取曲线数据

    // 读取前两行以获取坐标轴范围
    if (in.readLineInto(&line)) {
        QStringList fields = line.split(',');
        if (fields.size() >= 3 && fields.at(0) == "X Axis Range:") {
            xRangeLower = fields.at(1).toDouble();
            xRangeUpper = fields.at(2).toDouble();
        }
    }

    if (in.readLineInto(&line)) {
        QStringList fields = line.split(',');
        if (fields.size() >= 3 && fields.at(0) == "Y Axis Range:") {
            yRangeLower = fields.at(1).toDouble();
            yRangeUpper = fields.at(2).toDouble();
            rangesRead = true;  // 标记我们成功读取了范围
        }
    }

    // 读取剩余的数据
    while (in.readLineInto(&line)) {
        QStringList fields = line.split(',');  // 假设字段是用逗号分隔的
        if (fields.size() == 1 && line.startsWith("Graph")) {
            // 遇到新曲线的标识符时，将当前数据存入并准备读取新曲线
            if (!xData.isEmpty() && !yData.isEmpty()) {
                allXData.append(xData);
                allYData.append(yData);
                xData.clear();
                yData.clear();
            }
            readingCurveData = true;  // 开始读取新曲线数据
            continue;
        }

        if (fields.size() >= 2 && readingCurveData) {  // 至少需要两个字段：x 和 y 值
            bool ok1, ok2;
            double x = fields.at(0).toDouble(&ok1);
            double y = fields.at(1).toDouble(&ok2);
            if (ok1 && ok2) {  // 确保转换成功
                xData.append(x);
                yData.append(y);
            }
        }
    }

    // 处理最后一条曲线的数据
    if (!xData.isEmpty() && !yData.isEmpty()) {
        allXData.append(xData);
        allYData.append(yData);
    }

    file.close();

    // 创建一个新对话框
    QDialog *dialog = new QDialog(this);
    dialog->setWindowTitle("历史记录");
    QVBoxLayout *layout = new QVBoxLayout(dialog);

    // 创建 QCustomPlot
    QCustomPlot *customPlot = new QCustomPlot(dialog);
    layout->addWidget(customPlot);

    // 定义不同的颜色数组以区分曲线
    QVector<QColor> colors = {Qt::blue, Qt::red};  // 两条曲线使用不同的颜色

    // 遍历所有曲线并将它们添加到 QCustomPlot 中
    for (int i = 0; i < allXData.size(); ++i) {
        QVector<double> currentXData = allXData.at(i);
        QVector<double> currentYData = allYData.at(i);

        // 创建每条曲线并设置样式
        QCPGraph *graph = customPlot->addGraph();
        graph->setData(currentXData, currentYData);

        // 设置线条颜色和宽度
        graph->setPen(QPen(colors[i % colors.size()], 2));  // 使用颜色数组循环选择不同颜色，设置线宽为2
    }

    // 根据读取到的轴范围设置范围
    if (rangesRead) {
        customPlot->xAxis->setRange(xRangeLower, xRangeUpper);
        customPlot->yAxis->setRange(yRangeLower, yRangeUpper);
    } else {
        customPlot->rescaleAxes();  // 如果没有轴范围，重新调整比例
    }

    customPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);
    customPlot->setMinimumSize(QSize(400, 400));

    // 显示对话框
    dialog->exec();


}

void Widget::on_btn_SlaveInit_pressed()//初始化
{
    //serial.write(QByteArray::fromHex("234130303030303030308021"));//获取下位机状态
   /* checkCode = 0;
    if(!this->subData->serial.isOpen())
    {
        QMessageBox::warning(this,"warrning","串口没打开",QMessageBox::Ok);
        return ;
    }

    QByteArray * data = new QByteArray;
    data->append('#');//# 0x23
    data->append('A');//A 0x41

    data->append("00");//功能码 0 请求下位机最新状态
    checkCode += '0'; //数据包没有 就一个0
    checkCode += '0';
    data->append(checkCode&0xff);//拼接校验和
    data->append('!');// ! 0x21
    qDebug()<< data;
    qDebug() << checkCode;
    this->subData->serial.write(*data);
    checkCode = 0;*/

}

void Widget::on_btn_Start_released()//启动脉冲
{
    if(!this->subData->serial.isOpen())
    {
        QMessageBox::warning(this,"warrning","串口没打开",QMessageBox::Ok);
        return ;
    }

   // QByteArray * data = new QByteArray;
    checkCode = 0;
    auto reply = QMessageBox::question(this,"question","是否进行操作",QMessageBox::Yes|QMessageBox::No);
    if(QMessageBox::Yes == reply && !isRunning)
    {
        if(ui->spinBox_frequency->text() == "" || "0" == ui->spinBox_frequency->text() )
        {
            QMessageBox::warning(this,"warrning","频率不能为空或者0",QMessageBox::Ok);
            return ;
        }
        if(ui->spinBox_AddTimer->text() == "" || (6 > ui->spinBox_AddTimer->text().toInt() && ui->spinBox_AddTimer->text().toInt() <= 255 ))
        {

            QMessageBox::warning(this,"warrning","加速度时间不能小于6或者等于0且小于256",QMessageBox::Ok);
            return ;
        }
        if(ui->spinBox_SubTimer->text() == "" || (6 > ui->spinBox_SubTimer->text().toInt() && ui->spinBox_SubTimer->text().toInt() <= 255 ) )
        {

            QMessageBox::warning(this,"warrning","减速度时间不能小于6或者等于0且小于256",QMessageBox::Ok);
            return ;
        }
        if(ui->modifyCnt->text() == "")
        {
            QMessageBox::warning(this,"warrning","个数不能为空",QMessageBox::Ok);
            return ;
        }
         data->append("#A2");
        if("Y4" == ui->comboBox_DirTerminal->currentText())
        {
            data->append("4");   //方向端子  0=高电平  1=低电平
        }
        else if("Y5" == ui->comboBox_DirTerminal->currentText())
        {
            data->append("5");
        }
        else if("Y6" == ui->comboBox_DirTerminal->currentText())
        {
            data->append("6");
        }
        else if("Y7" == ui->comboBox_DirTerminal->currentText())
        {
            data->append("7");
        }


        if("Y0" == ui->comboBox_pulseChose->currentText())  //输出端子 0.1 .2 .3
        {
            data->append("0");
        }else if("Y1" == ui->comboBox_pulseChose->currentText())
        {
            data->append("1");
        }else if("Y2" == ui->comboBox_pulseChose->currentText())
        {
            data->append("2");
        }else if("Y3" == ui->comboBox_pulseChose->currentText())
        {
            data->append("3");
        }
        if("X1" == ui->comboBox_STOP->currentText())  //硬极限端子1 2 4 5
        {
            data->append("1");
        }
        else if("X2" == ui->comboBox_STOP->currentText())
        {
            data->append("2");
        }
        else if("X4" == ui->comboBox_STOP->currentText())
        {
            data->append("4");
        }
        else if("X5" == ui->comboBox_STOP->currentText())
        {
            data->append("5");
        }

        data->append(ui->spinBox_AddTimer->text());//加速时间
        data->append('&');
        data->append(ui->spinBox_SubTimer->text());//减速时间
        data->append('&');

        data->append(ui->spinBox_frequency->text());
        data->append("&");

        data->append(ui->modifyCnt->text());
        data->append("&");

        data->append(ui->sanpleFrequcency->text());
        data->append("&");

        checkCode = calculatePartialChecksum(*data,2);

        data->append(checkCode);
        data->append('!');
        this->subData->serial.write(*data);
        isRunning = true;
         ui->btn_Start->setText("运行中");
        //timer1->start(500);

     }
     else if((QMessageBox::Yes == reply) && isRunning) //停止运行
    {
        ui->btn_Start->setText("已停止");
        data->append("#A10");
        checkCode = 0x61;
        data->append(checkCode);
        data->append('!');
        this->subData->serial.write(*data);
        isRunning = false;
       // timer1->stop();
    }
    data->clear();
    checkCode = 0;

}

QByteArray Widget::packData(QString dirTerminal, QString outTerminal, QString hardTerminal, QString addTime, QString subTime, QString frequency, QString cnt)
{
    QByteArray tmp;
    checkCode = 0;
    tmp.append("#A2");
    tmp.append(dirTerminal);
    tmp.append(outTerminal);
    tmp.append(hardTerminal);
    tmp.append(addTime);
    tmp.append("&");
    tmp.append(subTime);
    tmp.append("&");
    tmp.append(frequency);
    tmp.append("&");
    tmp.append(cnt);
    tmp.append("&");
    checkCode = calculatePartialChecksum(tmp,2);
    tmp.append(checkCode);
    return tmp;
}

QByteArray Widget::packData2(QString code,QString dirTerminal, QString outTerminal, QString hardTerminal, QString addTime, QString subTime, QString frequency, QString cnt)//下位机的打包和计算校验和方式
{
    QByteArray tmp;
    checkCode = 0;
    tmp = "#&"+code.toLocal8Bit()+"&" + dirTerminal.toLocal8Bit() + "&" + outTerminal.toLocal8Bit() + "&" +
                hardTerminal.toLocal8Bit() + "&" + frequency.toLocal8Bit() + "&" +
               addTime.toLocal8Bit() + "&" + subTime.toLocal8Bit() + "&" + cnt.toLocal8Bit()+ "&";

    checkCode = calculatePartialChecksum(tmp,1);
    tmp.append(checkCode);
    return tmp;
}

uint8_t Widget:: calculatePartialChecksum(const QByteArray &data, int start) //计算校验和
{
    uint8_t checksum = 0;

    for (int i = start; i < data.length() && i < data.size(); ++i)
    {
        checksum += static_cast<uint8_t>(data[i]);
    }
    return checksum;
}

void Widget::handle_PulseSysCgf( QList<QByteArray> buffer)//下位机数据
{
    //
    if(QString::fromUtf8(buffer[3]) == "Y0")
    {
       ui->lineEdit_1->setText(QString::fromUtf8(buffer[2])); //方向端子
       ui->lineEdit_2->setText(QString::fromUtf8(buffer[3])); //输出端子
       ui->lineEdit_3->setText(QString::fromUtf8(buffer[4])); //硬极限端子
       ui->lineEdit_4->setText(QString::fromUtf8(buffer[5])); //脉冲频率
       ui->lineEdit_5->setText(QString::fromUtf8(buffer[6])); //加速时间
       ui->lineEdit_6->setText(QString::fromUtf8(buffer[7])); //减速时间
       ui->lineEdit_7->setText(QString::fromUtf8(buffer[8])); //脉冲个数
//       if(buffer[5].toInt() > 0)
//       {
//            ui->lineEdit_1->setText("ON");
//       }
//       else
//       {
//            ui->lineEdit_1->setText("OFF");
//       }
    }
    else if(QString::fromUtf8(buffer[3]) == "Y1")
    {
        ui->lineEdit_12->setText(QString::fromUtf8(buffer[2])); //方向端子
        ui->lineEdit_13->setText(QString::fromUtf8(buffer[3])); //输出端子
        ui->lineEdit_16->setText(QString::fromUtf8(buffer[4])); //硬极限端子
        ui->lineEdit_17->setText(QString::fromUtf8(buffer[5])); //脉冲频率
        ui->lineEdit_15->setText(QString::fromUtf8(buffer[6])); //加速时间
        ui->lineEdit_14->setText(QString::fromUtf8(buffer[7])); //减速时间
        ui->lineEdit_11->setText(QString::fromUtf8(buffer[8])); //脉冲个数   以上是Y1
//        if(buffer[5].toInt() > 0)
//        {
//             ui->lineEdit_12->setText("ON");
//        }
//        else
//        {
//             ui->lineEdit_12->setText("OFF");
//        }
    }
    else if(QString::fromUtf8(buffer[3]) == "Y2")
    {
        ui->lineEdit_19->setText(QString::fromUtf8(buffer[2])); //方向端子
        ui->lineEdit_20->setText(QString::fromUtf8(buffer[3])); //输出端子
        ui->lineEdit_23->setText(QString::fromUtf8(buffer[4])); //硬极限端子
        ui->lineEdit_24->setText(QString::fromUtf8(buffer[5])); //脉冲频率
        ui->lineEdit_22->setText(QString::fromUtf8(buffer[6])); //加速时间
        ui->lineEdit_21->setText(QString::fromUtf8(buffer[7])); //减速时间
        ui->lineEdit_18->setText(QString::fromUtf8(buffer[8])); //脉冲个数   以上是Y2
//        if(buffer[5].toInt() > 0)
//        {
//             ui->lineEdit_19->setText("ON");
//        }
//        else
//        {
//             ui->lineEdit_19->setText("OFF");
//        }
    }
    else if(QString::fromUtf8(buffer[3]) == "Y3")
    {
        ui->lineEdit_26->setText(QString::fromUtf8(buffer[2])); //方向端子
        ui->lineEdit_27->setText(QString::fromUtf8(buffer[3])); //输出端子
        ui->lineEdit_30->setText(QString::fromUtf8(buffer[4])); //硬极限端子
        ui->lineEdit_31->setText(QString::fromUtf8(buffer[5])); //脉冲频率
        ui->lineEdit_28->setText(QString::fromUtf8(buffer[6])); //加速时间
        ui->lineEdit_29->setText(QString::fromUtf8(buffer[7])); //减速时间
        ui->lineEdit_25->setText(QString::fromUtf8(buffer[8])); //脉冲个数   以上是Y3
//        if(buffer[5].toInt() > 0)
//        {
//             ui->lineEdit_26->setText("ON");
//        }
//        else
//        {
//             ui->lineEdit_26->setText("OFF");
//        }
    }
    updataXAxis(buffer[8].toInt(),buffer[5].toInt());


}

void Widget::handle_AllSysCgf( QList<QByteArray> buffer)//下位机数据
{
    if(QString::fromUtf8(buffer[3]) == "0")
    {
      ui->lineEdit_1->setText(QString::fromUtf8(buffer[2])); //方向端子
      ui->lineEdit_2->setText(QString::fromUtf8(buffer[3])); //输出端子
      ui->lineEdit_3->setText(QString::fromUtf8(buffer[4])); //硬极限端子
      ui->lineEdit_4->setText(QString::fromUtf8(buffer[5])); //脉冲频率
      ui->lineEdit_5->setText(QString::fromUtf8(buffer[6])); //加速时间
      ui->lineEdit_6->setText(QString::fromUtf8(buffer[7])); //减速时间
      ui->lineEdit_7->setText(QString::fromUtf8(buffer[8])); //脉冲个数
    }
    else if(QString::fromUtf8(buffer[3]) == "1")
    {
      ui->lineEdit_11->setText(QString::fromUtf8(buffer[2])); //方向端子
      ui->lineEdit_17->setText(QString::fromUtf8(buffer[3])); //输出端子
      ui->lineEdit_12->setText(QString::fromUtf8(buffer[4])); //硬极限端子
      ui->lineEdit_16->setText(QString::fromUtf8(buffer[5])); //脉冲频率
      ui->lineEdit_13->setText(QString::fromUtf8(buffer[6])); //加速时间
      ui->lineEdit_14->setText(QString::fromUtf8(buffer[7])); //减速时间
      ui->lineEdit_15->setText(QString::fromUtf8(buffer[8])); //脉冲个数
    }
    else if(QString::fromUtf8(buffer[3]) == "2")
    {
      ui->lineEdit_18->setText(QString::fromUtf8(buffer[2])); //方向端子
      ui->lineEdit_24->setText(QString::fromUtf8(buffer[3])); //输出端子
      ui->lineEdit_19->setText(QString::fromUtf8(buffer[4])); //硬极限端子
      ui->lineEdit_23->setText(QString::fromUtf8(buffer[5])); //脉冲频率
      ui->lineEdit_20->setText(QString::fromUtf8(buffer[6])); //加速时间
      ui->lineEdit_21->setText(QString::fromUtf8(buffer[7])); //减速时间
      ui->lineEdit_22->setText(QString::fromUtf8(buffer[8])); //脉冲个数
    }
    else if(QString::fromUtf8(buffer[3]) == "3")
    {
      ui->lineEdit_25->setText(QString::fromUtf8(buffer[2])); //方向端子
      ui->lineEdit_31->setText(QString::fromUtf8(buffer[3])); //输出端子
      ui->lineEdit_26->setText(QString::fromUtf8(buffer[4])); //硬极限端子
      ui->lineEdit_30->setText(QString::fromUtf8(buffer[5])); //脉冲频率
      ui->lineEdit_27->setText(QString::fromUtf8(buffer[6])); //加速时间
      ui->lineEdit_28->setText(QString::fromUtf8(buffer[7])); //减速时间
      ui->lineEdit_29->setText(QString::fromUtf8(buffer[8])); //脉冲个数
    }

}

void Widget::handle_LowComputerSysCgf(QList<QByteArray> buffer)
{

    ui->lineEdit_1->setText(QString::fromUtf8(buffer[2])); //方向端子
    ui->lineEdit_2->setText(QString::fromUtf8(buffer[3])); //输出端子
    ui->lineEdit_3->setText(QString::fromUtf8(buffer[4])); //硬极限端子
    ui->lineEdit_4->setText(QString::fromUtf8(buffer[5])); //脉冲频率
    ui->lineEdit_5->setText(QString::fromUtf8(buffer[6])); //加速时间
    ui->lineEdit_6->setText(QString::fromUtf8(buffer[7])); //减速时间
    ui->lineEdit_7->setText(QString::fromUtf8(buffer[8])); //脉冲个数   以上是Y0


    ui->lineEdit_12->setText(QString::fromUtf8(buffer[9]));  //方向端子
    ui->lineEdit_13->setText(QString::fromUtf8(buffer[10])); //输出端子
    ui->lineEdit_16->setText(QString::fromUtf8(buffer[11])); //硬极限端子
    ui->lineEdit_17->setText(QString::fromUtf8(buffer[12])); //脉冲频率
    ui->lineEdit_15->setText(QString::fromUtf8(buffer[13])); //加速时间
    ui->lineEdit_14->setText(QString::fromUtf8(buffer[14])); //减速时间
    ui->lineEdit_11->setText(QString::fromUtf8(buffer[15])); //脉冲个数   以上是Y1


    ui->lineEdit_19->setText(QString::fromUtf8(buffer[16])); //方向端子
    ui->lineEdit_20->setText(QString::fromUtf8(buffer[17])); //输出端子
    ui->lineEdit_23->setText(QString::fromUtf8(buffer[18])); //硬极限端子
    ui->lineEdit_24->setText(QString::fromUtf8(buffer[19])); //脉冲频率
    ui->lineEdit_22->setText(QString::fromUtf8(buffer[20])); //加速时间
    ui->lineEdit_21->setText(QString::fromUtf8(buffer[21])); //减速时间
    ui->lineEdit_18->setText(QString::fromUtf8(buffer[22])); //脉冲个数   以上是Y2


    ui->lineEdit_26->setText(QString::fromUtf8(buffer[23]));  //方向端子
    ui->lineEdit_27->setText(QString::fromUtf8(buffer[24]));  //输出端子
    ui->lineEdit_30->setText(QString::fromUtf8(buffer[25]));  //硬极限端子
    ui->lineEdit_31->setText(QString::fromUtf8(buffer[26]));  //脉冲频率
    ui->lineEdit_29->setText(QString::fromUtf8(buffer[27]));  //加速时间
    ui->lineEdit_28->setText(QString::fromUtf8(buffer[28]));  //减速时间
    ui->lineEdit_25->setText(QString::fromUtf8(buffer[29]));  //脉冲个数   以上是Y3

}

void Widget:: updateStatusHandler(bool stauts) //更新启动按钮
{
    if(true == stauts)
    {
        ui->btn_Start->setText("运行中");
        isRunning = true;
    }
}

void Widget::jerkHandler()//硬极限端子
{
    qDebug() << "触碰到硬极限端子";
    ui->btn_Start->setText("已停止");
    isRunning = false;
}
void Widget::on_btn_ModifyPulFre_released()//修改脉冲频率
{
     // serial.write(QByteArray::fromHex("2341303030303030305021"));
    if(!this->subData->serial.isOpen())
    {
        QMessageBox::warning(this,"warrning","串口没打开",QMessageBox::Ok);
        return ;
    }
    checkCode = 0;
    //QByteArray * data = new QByteArray;
    data->append('#');//# 0x23
    data->append('A');//A 0x41
    data->append('4');//4 0X34
    checkCode += '4';
    int value = ui->spinBox_frequency->value();
    if(value > 0)
    {
         data->append('0'); // 0 0x30
         checkCode += '0';
    }
    else if(value < 0)
    {
         data->append('1');//1 0x31
         checkCode += '1';
    }else
    {
        if(0 == value)
        {
            QMessageBox::warning(this,"warrning","频率不能为0",QMessageBox::Ok);
            return ;

        }
    }
    QString  temp = QString::number(abs(value)); //负数直接转整数 因为功能码后面第一位是符号位
    for(int i = 0;i < temp.length();i++)//数据包的最高位补0
    {

        checkCode += temp[i].unicode();
    }
    data->append(temp);
    data->append(checkCode&0xff);//拼接校验和
    data->append('!');// ! 0x21
    qDebug()<< data;
    qDebug() << checkCode;
    this->subData->serial.write(*data);
    checkCode = 0;
    data->clear();

}

void Widget::on_btn_ModifyPulCnt_released()//修改脉冲个数
{
    if(!this->subData->serial.isOpen())
    {
        QMessageBox::warning(this,"warrning","串口没打开",QMessageBox::Ok);
        return ;
    }
     QString value = ui->modifyCnt->text();
    if( value == "")
    {
        QMessageBox::warning(this,"warrning","个数不能为空",QMessageBox::Ok);
        return ;
    }
    checkCode = 0;
   // QByteArray * data = new QByteArray;
    data->append('#');//# 0x23
    data->append('A');//A 0x41
    data->append('5');//4 0X34
    checkCode += '5';


    for(int i = 0;i < value.length();i++)
    {
        checkCode += (uint8_t)value[i].unicode();
    }

    data->append(value);
    data->append(checkCode&0xff);//拼接校验和
    data->append('!');// ! 0x21
    qDebug()<< data;
    qDebug() << checkCode;
    this->subData->serial.write(*data);
    data->clear();
    checkCode = 0;

}

void Widget::reslvePack(QByteArray pack)//解包
{
   auto data2 =  pack.split('&');
  // checkHeartBeat(pack);
   ui->acceptText->insertPlainText(pack);
   ui->acceptText->insertPlainText("\r\n");
   int i = 0;
   checkCode = 0;
   if(data2[0] != "#")
         return ;
   pack = pack.remove(0,1);

   qDebug() << "pack  :"<<pack;
   while(i < (pack.length()-1))
   {
        checkCode += pack[i];
        ++i;
   }
   qDebug() << "qiang zhuan de data :"<<static_cast<uint8_t>(pack[pack.length()-1]);
    if(checkCode != static_cast<uint8_t>(pack[pack.length()-1]))
    {
        qDebug() << "main thread：checkcode :"<<checkCode << "x下位机的校验和 :"<< pack[pack.length()-1];
        return ;
    }
    else
    {
        qDebug() << "check code true";
    }

   switch (pack[1] - '0')
   {
       case  0://下位机断电
             ui->btn_Start->setText("已停止");
             this->subData->serial.close();//断开串口
             ui->Button_Link->setText("打开串口");
             QMessageBox::warning(this,"ERROR","下位机已停止",QMessageBox::Ok);
       break;
       case 1://下位机碰到硬极限端子
               ui->btn_Start->setText("已停止");
               isRunning = false;
       break;
       case 2://下位机所有参数
              handle_PulseSysCgf(data2);
              ui->btn_Start->setText("运行中");
       break;
       case 3: // 获取下位机参数配置
               handle_LowComputerSysCgf(data2);
       break;
   }
}
int Widget::unPackData(QByteArray pack)
{
    auto data2 =  pack.split('&');
    int i = 0;
    checkCode = 0;
    if(data2[0] != "#")
          return -1;
    pack = pack.remove(0,1);

    qDebug() << "pack  :"<<pack;
    while(i < (pack.length()-1))
    {
         checkCode += pack[i];
         ++i;
    }
    qDebug() << "qiang zhuan de data :"<<static_cast<uint8_t>(pack[pack.length()-1]);
     if(checkCode != static_cast<uint8_t>(pack[pack.length()-1]))
     {
         qDebug() << "main thread：checkcode :"<<checkCode << "x下位机的校验和 :"<< pack[pack.length()-1];
         return -2;
     }
     else
     {
         qDebug() << "check code true";
     }

    switch (pack[1] - '0')
    {
        case  0://下位机断电
              return 0;
        break;
        case 1://下位机碰到硬极限端子
                return 1;
        break;
        case 2://下位机所有参数
               return 2;
        break;
        case 3: // 获取下位机参数配置
              return 3;
        break;
    }
    return 404;//找不到对应的功能码
}

void Widget:: hotPlug()
{
     ui->comboBox_serialPort->clear();
     auto list = QSerialPortInfo::availablePorts();
     for(auto&info:list)
     {
          ui->comboBox_serialPort->addItem(info.portName()+":"+info.description(),info.portName());
         if(lastPortName == info.portName())
         {
            return;
         }
     }

     auto reply = QMessageBox::question(this,"question","串口已断开，是否重新链接",QMessageBox::Yes|QMessageBox::No);
     if(QMessageBox::Yes == reply)
     {
           int i = 50;
          qDebug() << "last portname:"<<lastPortName;
          QMessageBox::information(this,"通知","正在尝试重新链接...",QMessageBox::Ok);

          ui->comboBox_serialPort->clear();
          list = QSerialPortInfo::availablePorts();
          for(auto&info:list)
          {
               ui->comboBox_serialPort->addItem(info.portName()+":"+info.description(),info.portName());
              if(lastPortName == info.portName())
              {
                 ui->Button_Link->pressed();
                 while(--i);
                 ui->Button_Link->pressed();
              }
          }

  }
     else
     {
         this->subData->serial.close();
         ui->btn_Start->setText("已停止");
         ui->Button_Link->setText("连接串口");
          QMessageBox::information(this,"ERROR","串口已断开",QMessageBox::Ok);
          timer1->stop();
          subThread->quit();

         return ;
     }
 }

void Widget::checkHeartBeat(QByteArray pack)
{

     if(!pack.isEmpty())
     {
         // QMessageBox::information(this,"ERROR","请检查串口连接",QMessageBox::Ok);

     }

 }

void Widget::on_pushButton_released() //串口刷新按钮
{
    ui->comboBox_serialPort->clear();
     auto list = QSerialPortInfo::availablePorts();
    for(auto&info:list)
    {
        qDebug()<<info.description()<<info.portName();
        ui->comboBox_serialPort->addItem(info.portName()+":"+info.description(),info.portName());
    }
}

void Widget::on_btn_ClearGraphic_released()
{
    ui->plot->graph(0)->setData(QVector<double>(),QVector<double>());
    ui->plot->graph(1)->setData(QVector<double>(),QVector<double>());
    lastXPoint = -10;
    ui->plot->replot();
}



